from mbserver.server.lib import utils
from django.utils.encoding import smart_unicode
import logging
log = logging.getLogger('metabus')

class Parser():
    def __init__(self, parser):
        self.parser = parser
        self.doc = None
        self.items = []

    def reset(self):
        self.doc = None
        self.items = []

    def feed(self, doc):
        self.doc = doc
        
import re
class RegExpParser(Parser):

    def __init__(self, parser):
        if parser.type != 'regexp':
            raise Exception('Invalid Parser Type')
        Parser.__init__(self, parser)

    def _parse_encoding_(self, doc):
        """
        Matches with the chaset content in the meta tag
        """
        e = re.compile('(?i)<meta.*?charset=([\w\d-]*).*?>', re.DOTALL|re.UNICODE|re.LOCALE)
        matches = e.findall(doc)

        if len(matches)>0:
            return matches[0]
        else:
            return None

    def feed(self, doc):
        encoding = self._parse_encoding_(doc)        

        if encoding:
            doc = smart_unicode(doc, encoding=encoding)
        else:
            doc = smart_unicode(doc)
        Parser.feed(self, doc)
        trx = re.compile(self.parser.regexp_title, re.DOTALL|re.UNICODE|re.LOCALE)
        drx = re.compile(self.parser.regexp_description, re.DOTALL|re.UNICODE|re.LOCALE)
        lrx = re.compile(self.parser.regexp_link, re.DOTALL|re.UNICODE|re.LOCALE)
    
        titles = trx.findall(doc)
        descs  = drx.findall(doc)
        links  = lrx.findall(doc)

        if len(titles) == len(descs) == len(links):
            for i in range(len(titles)):
                self.items.append({
                    'title': titles[i],
                    'description': descs[i],
                    'link': links[i],
                })
        else:
            raise Exception('Diferent number of matches')

import sgmllib
class XMLParser(sgmllib.SGMLParser):
    """
        Xml Parser:
        This parser can parse not well formed XML documents.
    """
    def reset(self):
        self.items = []
        self.currentTag = None
        self.currentValue = ''
        self.initem = 0
        sgmllib.SGMLParser.reset(self)

    def start_item(self, attrs):
        # set a flag that we're within an RSS item now
        self.items.append({})
        self.initem = 1

    def end_item(self):
        # OK, we're out of the RSS item
        self.initem = 0

    def unknown_starttag(self, tag, attrs):
        self.currentTag = tag

    def unknown_endtag(self, tag):
        # if we're within an RSS item, save the data we've buffered
        if self.initem:
            # decode entities and strip whitespace
            self.currentValue = decodeEntities(self.currentValue.strip())
            self.items[-1][self.currentTag] = self.currentValue
        self.currentValue = ''

    def handle_data(self, data):
        # buffer all text data
        self.currentValue += data

    def handle_entityref(self, data):
        # buffer all entities
        self.currentValue += '&' + data
    handle_charref = handle_entityref

def decodeEntities(data):
    # in case our document *was* encoded correctly, we'll
    # need to decode the XML entities manually; sgmllib
    # will not do it for us
    data = data.replace('&lt;', '<')
    data = data.replace('&gt;', '>')
    data = data.replace('&quot;', '"')
    data = data.replace('&apos;', "'")
    data = data.replace('&amp;', '&')
    return data

class RssParser(Parser):
    
    def __init__(self, parser):
        if parser.type != 'rss':
            raise Exception('Invalid Parser Type')
        self.parser = XMLParser()
        self.items = self.parser.items

    def reset(self):
        self.parser.reset()
        self.items = self.parser.items

    def feed(self, doc):
        self.parser.feed(doc)
        self.items = self.parser.items
